using System;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Xml;
namespace XTCast.Radio
{
	
	/// <summary>A convenience subclass of Properties that makes it easy to read properties
	/// from a file, and to get property values as integers or classnames.
	/// </summary>
	
	public class RadioProperties:System.Collections.Specialized.NameValueCollection
	{
		
		/// <summary>Default properties. Set when the app initializes. </summary>
		public static RadioProperties sDefaults = new RadioProperties(System.Configuration.ConfigurationSettings.AppSettings);

		public static RadioProperties GetConfig( String fname )
		{
			// Open and parse configuration file for specified
			// assembly, returning collection to caller for future
			// use outside of this class.
			//
			try
			{
				const string nodeName = "stationSettings";

				XmlDocument doc = new XmlDocument();
				doc.Load(new XmlTextReader(fname));
            
				XmlNodeList nodes = doc.GetElementsByTagName(nodeName);

				foreach( XmlNode node in nodes )
				{
					if( node.LocalName == nodeName )
					{
						NameValueSectionHandler handler = new NameValueSectionHandler();
						return new RadioProperties((NameValueCollection)handler.Create(null, null, node));
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return(null);
		}

		public RadioProperties(NameValueCollection nvcoll):base(nvcoll)
		{
		}
		
		static public RadioProperties getDefaults() {
			return sDefaults;
		}

		public System.String getProperty(System.String name)
		{
			System.String value_Renamed = this[name];
			if ((System.Object) value_Renamed != null)
				value_Renamed = value_Renamed.Trim();
			return value_Renamed;
		}

		public virtual int getIntProperty(System.String name, int deflt)
		{
			System.String str = this[name];
			if ((System.Object) str == null)
				return deflt;
			else
			{
				try
				{
					return System.Int32.Parse(str);
				}
				catch (System.FormatException x)
				{
					WARN_VALUE(name, str, "is not a valid number -- will use default value " + deflt);
					return deflt;
				}
			}
		}
		
		
		/// <summary>Looks up a classname-valued property, returning a new instance of that class.
		/// If the property is not defined, null is returned.
		/// If the class does not exist or cannot be instantiated, a warning is generated
		/// and null returned. 
		/// </summary>
		public virtual System.Object getObjectProperty(System.String name, object[] args)
		{
			if (this[name]==null)
				return propertyValueToObject(name, sDefaults[name], args);
			else
				return propertyValueToObject(name, this[name], args);
		}
		
		
		/// <summary>Instantiates an object, given the classname read from a property.
		/// If the instantiation fails, a warning is printed and null is returned. 
		/// </summary>
		public virtual System.Object propertyValueToObject(System.String propName, System.String className, object[] args)
		{
			if ((System.Object) className != null && className.IndexOf((System.Char) '.') < 0)
				className = "XTCast.Radio." + className; // Default package nam
			try	{
				return System.Activator.CreateInstance(System.Type.GetType(className),args);
			} catch (System.Exception t) {
				Log.Error(this,new Exception(propName + "=" + className + " could not be instantiated:",t));
				return null;
			}
		}
		
		public virtual System.IO.DirectoryInfo GetDirectory(String name) {
			return GetDirectory(name,sDefaults[name]);
		}

		public virtual System.IO.DirectoryInfo GetDirectory(String name, String def)
		{
			System.String fname = this[name];

			if (fname == null)
				fname = def;

			if (fname == null) {
				WARN_VALUE(name, fname, "is not set!");
				return null;
			}

			if (!System.IO.Directory.Exists(fname))
			{
				WARN_VALUE(name, fname, "is not an existing directory!");
				return null;
			}
			return new System.IO.DirectoryInfo(fname);
		}
		
		private void  WARN_VALUE(System.String name, System.String value_Renamed, System.String message)
		{
			Log.Warn( "RadioProperties", "Property '" + name + "'s value is '" + value_Renamed + "' which " + message);
		}
	}
}